//
// Created by 张超 on 2024/5/6.
//

#include "trade.h"
#include <cstring>
#include <iostream>
#include <thread>
#include <chrono>
#include <utility>

using namespace HTFTS;

trade::trade(const std::string &FullConfigPath) :
        traderAPI(HTFTS::HTFTSTraderAPI::CreateTraderAPI(FullConfigPath.c_str())),
        mReqId(0), mBatchId(0), mOrderRef(0) {
    memset(&mUser, 0x00, sizeof(mUser));
    api_stat = false;
    sourceTerminalInfo = "mac-address";
}

void trade::Start() {

    if (HTFTS::APIResult::SUCCESS == traderAPI->ConnectServer(this)) {
        mConnetSatus = ConnectStatus::RECONNECTING;
        std::cout << "Send ConnectServer request to server succ ..." << std::endl;
        //traderAPI->ReqQrySysTradeDate(mReqId);
    } else {

        std::cout << "Send ConnectServer request to server fail ..., sleep 3s" << std::endl;
    }

}

void trade::OnConnected() {
    std::cout << "[OnConnected] Connected to trading server OK." << std::endl;
    mConnetSatus = ConnectStatus::CONNECTED;
    traderAPI->ReqQrySysTradeDate(mReqId);
    //api_stat = true;
    // 为了便于调试, 这里直接发起用户登陆

}

void trade::RspQrySysTradeDateInfo(HTFTS::TradeDateInfo *pTradeDateInfo, HTFTS::ErrorInfoField *pErrorInfo,
                                   HTFTS::RequestIDType reqId) {
    std::cout << "errorid" << pErrorInfo->errorId << std::endl;
    std::cout << "errormsg" << pErrorInfo->errorMessage << std::endl;

    std::cout << "currTradeDate" << pTradeDateInfo->currTradeDate << std::endl;
    std::cout << "lastTradeDate" << pTradeDateInfo->lastTradeDate << std::endl;
    std::cout << "nextTradeDate" << pTradeDateInfo->nextTradeDate << std::endl;
}


//void trade::setUser(const char *custid, const char *password) {
//    m_CustomerId = custid;
//    m_Password = password;
//}

void trade::UserLogin(ReqUserLoginField *pField) {
    ReqUserLoginField reqUserLoginField = {0}; //推荐的结构体初始化方式，方便结构体扩展和api版本间的兼容性
    strncpy(reqUserLoginField.cert_no, pField->cert_no, sizeof(reqUserLoginField.cert_no));
    reqUserLoginField.cust_type = CustType::CustNoTYpe;
    strncpy(reqUserLoginField.password, pField->password, sizeof(reqUserLoginField.password));
    strncpy(reqUserLoginField.sourceTerminalInfo, sourceTerminalInfo.c_str(),
            sizeof(reqUserLoginField.sourceTerminalInfo));
    if (APIResult::SUCCESS == traderAPI->ReqUserLogin(&reqUserLoginField, ++mReqId)) {
        std::cout << "Send ReqUserLogin request to server succ ..." << std::endl;
    } else {
        std::cout << "Send ReqUserLogin request to server fail ..., sleep 3s" << std::endl;
    }
}

void trade::OnRspUserLogin(RspUserLoginField *pRspUserLogin, ErrorInfoField *errorInfo, RequestIDType reqId) {
    if (0 == errorInfo->errorId) //登录成功
    {
        std::cout << "User login OK, RequestId=" << reqId << std::endl;
        std::cout << "会话号    :" << pRspUserLogin->sessionId << std::endl;
        std::cout << "报单引用号:" << pRspUserLogin->orderRefBase << std::endl;
        std::cout << "批量委托号:" << pRspUserLogin->batchIdBase << std::endl;
        std::cout << "客户姓名    :" << pRspUserLogin->customerName << std::endl;
        std::cout << "交易日期    :" << pRspUserLogin->tradeDate << std::endl;

        mOrderRef = pRspUserLogin->orderRefBase;
        strncpy(mUser.token, pRspUserLogin->token, sizeof(mUser.token));
        strncpy(mUser.user.user_id, pRspUserLogin->user_id, sizeof(mUser.user.user_id));
        strncpy(mUser.user.cust_id, pRspUserLogin->user_id, sizeof(mUser.user.cust_id));

    } else {
        std::cout << "User login fail ..., RequestId=" << reqId << std::endl;
        api_stat = true;
        PrintErrorInfoField(errorInfo, reqId);
    }
}

void trade::OnRtnSubscribe(RspUser *pUser, HTFTS::ErrorInfoField *errorMsgRsp) {
    std::cout << "OnRtnSubscribe OK." << "  user_id=" << pUser->user_id << std::endl;

    if (0 == errorMsgRsp->errorId) {
        //系统已经就绪，可以进行下单，查询等操作了：
        //查询委托 QrySingleOrder();
        //查询系统状态 traderAPI->ReqQrySysInfo(1);
        api_stat = true;
    } else {
        std::cout << "Recv RtnSubscribe Error: Error ID = " << errorMsgRsp->errorId << ", error Msg = "
                  << errorMsgRsp->errorMessage << std::endl;
        //订阅失败，可做登录失败处理，并重新登录
        api_stat = true;
    }
}

void trade::OnRspHolderNoField(RspUser *pUser, RspHolderNoField *pRspHolderNoField, RequestIDType reqId, bool isLast) {
    std::cout << "股东代码返回信息回调：" << std::endl;
    std::cout << "客户号      = " << pRspHolderNoField->userId << std::endl;
    std::cout << "市场代码    = " << pRspHolderNoField->exchangeId << std::endl;
    std::cout << "股东代码    = " << pRspHolderNoField->holderId << std::endl;
    PrintErrorInfoField(pUser);
}

void trade::SingleOrderInsert(ReqSingleOrderInsertField *pField) {
    ReqSingleOrderInsertField reqSingleOrderInsertSHA = {};  //推荐的结构体初始化方式，方便结构体扩展和api版本间的兼容性
    reqSingleOrderInsertSHA.order.exchangeId = pField->order.exchangeId;
    strncpy(reqSingleOrderInsertSHA.order.securityId, pField->order.securityId,
            sizeof(reqSingleOrderInsertSHA.order.securityId));
    reqSingleOrderInsertSHA.order.totalOriginalVolume = pField->order.totalOriginalVolume;
    reqSingleOrderInsertSHA.order.limitPrice = pField->order.limitPrice;
    strncpy(reqSingleOrderInsertSHA.order.direction, pField->order.direction,
            sizeof(reqSingleOrderInsertSHA.order.direction));
    reqSingleOrderInsertSHA.order.orderType = pField->order.orderType;
    ++mOrderRef;
    reqSingleOrderInsertSHA.order.orderRef = mOrderRef;
    strncpy(reqSingleOrderInsertSHA.order.sourceTerminalInfo, sourceTerminalInfo.c_str(),
            sizeof(reqSingleOrderInsertSHA.order.sourceTerminalInfo));
    ++mReqId;


    auto ret = traderAPI->ReqSingleOrderInsert(&mUser, &reqSingleOrderInsertSHA, mReqId);

    if (APIResult::SUCCESS == ret) {
        std::cout << "SingleOrderInsert OK." << std::endl;
    } else {
        std::cout << "SingleOrderInsert Error: Error ID = " << ret << std::endl;
    }
}

void trade::PrintErrorInfoField(ErrorInfoField *pErrorInfo, RequestIDType reqId) {
    std::cout << "    错误代码        ：" << pErrorInfo->errorId << std::endl;
    std::cout << "    错误信息        ：" << pErrorInfo->errorMessage << std::endl;
    std::cout << "    请求编号        ：" << reqId << std::endl;
}

void trade::PrintErrorInfoField(RspUser *pUser) {
    std::cout << "    客户号          ：" << pUser->cust_id << std::endl;
    std::cout << "    操作员编号      ：" << pUser->user_id << std::endl;
}

void trade::OnRtnOrder(RspUser *pUser, OrderField *pOrderFiled, ErrorInfoField *pErrorInfoField, RequestIDType reqId) {
    //1 建议此回报过滤，不处理
    if (1 == pOrderFiled->cancelFlag2) {
        return;
    }

    //2 失败后操作 此处进行回滚，客户可自行决定处理逻辑
    if (pErrorInfoField && 0 != pErrorInfoField->errorId) {

        //2.5 柜台拒绝或交易所拒绝错误信息打印
        PrintErrorInfoField(pUser, pErrorInfoField, reqId);
    }
        //3 成功后操作 客户可自行决定处理逻辑
    else {
        std::cout << "委托推送" << std::endl
                  << "reqId" << '\t'
                  << "sesId" << '\t'
                  << "ordRef" << '\t'
                  << "ordId" << '\t'
                  << "secId" << '\t'
                  << "ordSts" << '\t'
                  << "entrust" << '\t'
                  << "traded" << '\t'
                  << "cancelled" << '\t'
                  << std::endl
                  << reqId << '\t'
                  << pOrderFiled->sessionId << '\t'
                  << pOrderFiled->orderRef << '\t'
                  << pOrderFiled->orderId << '\t'
                  << pOrderFiled->securityId << '\t'
                  << pOrderFiled->orderStatus << '\t'
                  << pOrderFiled->totalOriginalVolume << '\t'
                  << pOrderFiled->tradedVolume << '\t'
                  << pOrderFiled->cancelVolume << '\t'
                  << std::endl
                  << std::endl;
        pOrderField_m = *pOrderFiled;
    }
}

void trade::PrintErrorInfoField(RspUser *pUser, ErrorInfoField *pErrorInfo, RequestIDType reqId) {
    std::cout << "    客户号          ：" << pUser->cust_id << std::endl;
    std::cout << "    操作员编号      ：" << pUser->user_id << std::endl;
    std::cout << "    错误代码        ：" << pErrorInfo->errorId << std::endl;
    std::cout << "    错误信息        ：" << pErrorInfo->errorMessage << std::endl;
    std::cout << "    请求编号        ：" << reqId << std::endl;
}

